#!/bin/sh
#
# This is part of OpenIPC.org project | 2022.01.19
#

# Board
board=demo

# SoC detect
chipid=$(ipcinfo --chip-name)

# Memory config
mem_start=0x80000000 # phy mem start

mem_total=$(fw_printenv -n totalmem | tr -d 'M')
mem_total=${mem_total:=64}

os_mem_size=$(fw_printenv -n osmem | tr -d 'M')
os_mem_size=${os_mem_size:=32}

SNS_TYPE0=imx327 # sensor type
SNS_TYPE1=NULL   # sensor type
YUV_TYPE0=0      # 0 -- raw, 1 -- bt1120/DC, 2 --bt656

report_error() {
    echo "******* Error: There's something wrong, please check! *****"
    exit 1
}

insert_osal() {
    MMZ=$(awk -F '=' '$1=="mmz"{print $2}' RS=" " /proc/cmdline)
    if [ -z "$MMZ" ]; then
        insmod hi_osal.ko anony=1 mmz_allocator=hisi mmz=anonymous,0,$mmz_start,$mmz_size || report_error
    else
        insmod cma_osal.ko anony=1 mmz_allocator=cma mmz=$MMZ || report_error
    fi
}

insert_detect() {
    cd /lib/modules/4.9.37/hisilicon
    insert_osal
    insmod sys_config.ko chip=${chipid} sensors=sns0=$SNS_TYPE0,sns1=$SNS_TYPE1, g_cmos_yuv_flag=$YUV_TYPE0
    insmod hi3516cv500_base.ko
    insmod hi3516cv500_isp.ko
    insmod hi_sensor_i2c.ko
    insmod hi_sensor_spi.ko
}

remove_detect() {
    rmmod -w hi_sensor_spi
    rmmod -w hi_sensor_i2c
    rmmod -w hi3516cv500_isp
    rmmod -w hi3516cv500_base
    rmmod -w sys_config
    rmmod -w hi_osal &> /dev/null
    rmmod -w cma_osal &> /dev/null
}

insert_audio() {
    insmod hi3516cv500_aio.ko
    insmod hi3516cv500_ai.ko
    insmod hi3516cv500_ao.ko
    insmod hi3516cv500_aenc.ko
    insmod hi3516cv500_adec.ko
    insmod hi3516cv500_acodec.ko
    #    insmod extdrv/hi_tlv320aic31.ko
    echo "insert audio"
}

remove_audio() {
    rmmod -w hi3516cv500_acodec
    #    rmmod -w hi_tlv320aic31.ko
    rmmod -w hi3516cv500_adec
    rmmod -w hi3516cv500_aenc
    rmmod -w hi3516cv500_ao
    rmmod -w hi3516cv500_ai
    rmmod -w hi3516cv500_aio

    echo "remove audio"
}

insert_isp() {
    insmod hi3516cv500_isp.ko
}

insert_gyro() {
    insmod extdrv/hi_spi.ko
    insmod hi3516cv500_gyrodis.ko
    insmod hi3516cv500_motionfusion.ko
    insmod extdrv/motionsensor_mng.ko
    insmod extdrv/motionsensor_chip.ko
}

remove_gyro() {
    rmmod -w motionsensor_chip
    rmmod -w motionsensor_mng
    rmmod -w hi3516cv500_motionfusion
    rmmod -w hi3516cv500_gyrodis
    rmmod -w hi_spi
}

sys_config(){
    bt656_pinmux(){
        devmem 0x114f0040 32 0x2
        devmem 0x114f0044 32 0x2
        devmem 0x114f0048 32 0x2
        devmem 0x114f004c 32 0x2
        devmem 0x114f0050 32 0x2
        devmem 0x114f0054 32 0x2
        devmem 0x114f0058 32 0x2
        devmem 0x114f005c 32 0x2
        devmem 0x114f0068 32 0x2
    }
    bt656_pinmux;
}

insert_ko() {
    # driver load
    insert_osal
    # sys config
    insmod sys_config.ko chip=${chipid} sensors=sns0=$SNS_TYPE0,sns1=$SNS_TYPE1, g_cmos_yuv_flag=$YUV_TYPE0

    sys_config;

    # insmod hi_tzasc.ko
    insmod hi3516cv500_base.ko
    insmod hi3516cv500_sys.ko
    insmod hi3516cv500_tde.ko
    insmod hi3516cv500_rgn.ko
    insmod hi3516cv500_gdc.ko
    insmod hi3516cv500_vgs.ko
    insmod hi3516cv500_dis.ko
    insmod hi3516cv500_vi.ko
    insert_isp
    insmod hi3516cv500_vpss.ko
    insmod hi3516cv500_vo.ko
    # insmod hifb.ko video="hifb:vram0_size:1024"     # default fb0:576p

    insmod hi3516cv500_chnl.ko
    insmod hi3516cv500_vedu.ko
    insmod hi3516cv500_rc.ko
    insmod hi3516cv500_venc.ko
    insmod hi3516cv500_h264e.ko
    insmod hi3516cv500_h265e.ko
    insmod hi3516cv500_jpege.ko

    insmod hi3516cv500_ive.ko save_power=1
    # insmod hi_ipcm.ko
    # insmod hi3516cv500_nnie.ko nnie_save_power=1 nnie_max_tskbuf_num=32
    insmod hi_pwm.ko
    insmod hi_piris.ko
    insmod hi_sensor_i2c.ko
    insmod hi_sensor_spi.ko
    # insmod extdrv/hi_sil9136.ko norm=12    #1080P@30fps for umap7p
    # insmod extdrv/mpu_bosch.ko

    insert_audio

    insmod hi_mipi_rx.ko
    # insmod hi_mipi_tx.ko
    # insmod hi_user.ko

    # insert_gyro
    insmod hi3516cv500_wdt.ko
}

remove_ko() {
    rmmod -w hi3516cv500_wdt
    # rmmod_gyro
    # rmmod -w hi_user
    remove_audio
    # rmmod -w hi_mipi_tx
    rmmod -w hi_mipi_rx
    #rmmod -w hi_sil9136 &> /dev/null
    rmmod -w hi_piris
    rmmod -w hi_pwm

    # rmmod -w hi3516cv500_nnie nnie_save_power=1 nnie_max_tskbuf_num=32
    # rmmod -w hi_ipcm
    rmmod -w hi3516cv500_ive
    rmmod -w hi3516cv500_rc
    rmmod -w hi3516cv500_jpege
    rmmod -w hi3516cv500_h264e
    rmmod -w hi3516cv500_h265e
    rmmod -w hi3516cv500_venc
    rmmod -w hi3516cv500_vedu
    rmmod -w hi3516cv500_chnl
    # rmmod -w hifb
    # rmmod -w hi3516cv500_vo
    rmmod -w hi3516cv500_vpss
    rmmod -w hi3516cv500_isp
    rmmod -w hi3516cv500_vi
    rmmod -w hi3516cv500_gdc
    rmmod -w hi3516cv500_dis
    rmmod -w hi3516cv500_vgs
    rmmod -w hi3516cv500_rgn
    rmmod -w hi3516cv500_tde

    rmmod -w hi_sensor_i2c &>/dev/null
    rmmod -w hi_sensor_spi &>/dev/null

    # rmmod -w mpu_bosch
    rmmod -w hi3516cv500_sys
    rmmod -w hi3516cv500_base
    # rmmod -w hi_tzasc
    rmmod -w sys_config
    rmmod -w hi_osal
}

sys_restore() {
    sns_config
}

load_usage()
{
	echo "Usage:  ./load_hisilicon [-option] [sensor_name]"
	echo "options:"
	echo "    -i                       insert modules"
	echo "    -r                       remove modules"
	echo "    -a                       remove modules first, then insert modules"
	echo "    -sensor sensor_name      config sensor type [default: imx307]"
	echo "    -h                       help information"
	echo -e "Available sensors: gc2053 imx307 imx327 imx335 os05a sc2231 sc2235 sc4236 sc3235 sc4236 etc."
	echo -e "for example: ./load_hisilicon -i -sensor imx307 -osmem 32M -board demo -yuv0 0\n"
}

calc_mmz_info() {
    mmz_start=$(echo "$mem_start $os_mem_size" |
        awk 'BEGIN { temp = 0; }
    {
        temp = $1/1024/1024 + $2;
    }
    END { printf("0x%x00000\n", temp); }')

    mmz_size=$(echo "$mem_total $os_mem_size" |
        awk 'BEGIN { temp = 0; }
    {
        temp = $1 - $2;
    }
    END { printf("%dM\n", temp); }')
    echo "mmz_start: $mmz_start, mmz_size: $mmz_size"
}

######################parse arg###################################
b_arg_sensor0=0
b_arg_sensor1=0
b_arg_yuv_type0=0
b_arg_insmod=0
b_arg_remove=0
b_arg_restore=0
b_arg_total_mem=0
b_arg_os_mem=0

for arg in $@; do
    if [ $b_arg_sensor0 -eq 1 ]; then
        b_arg_sensor0=0
        SNS_TYPE0=$arg
    fi
    if [ $b_arg_sensor1 -eq 1 ]; then
        b_arg_sensor1=0
        SNS_TYPE1=$arg
    fi
    if [ $b_arg_total_mem -eq 1 ]; then
        b_arg_total_mem=0
        mem_total=$arg

        if [ -z $mem_total ]; then
            echo "[error] mem_total is null"
            exit
        fi
    fi

    if [ $b_arg_os_mem -eq 1 ]; then
        b_arg_os_mem=0
        os_mem_size=$arg

        if [ -z $os_mem_size ]; then
            echo "[error] os_mem_size is null"
            exit
        fi
    fi

    if [ $b_arg_yuv_type0 -eq 1 ]; then
        b_arg_yuv_type0=0
        YUV_TYPE0=$arg
    fi

    case $arg in
    "-i")
        b_arg_insmod=1
        ;;
    "-r")
        b_arg_remove=1
        ;;
    "-a")
        b_arg_insmod=1
        b_arg_remove=1
        ;;
    "-h")
        load_usage
        ;;
    "-sensor0")
        b_arg_sensor0=1
        ;;
    "-sensor")
        b_arg_sensor0=1
        ;;
    "-sensor1")
        b_arg_sensor1=1
        ;;
    "-osmem")
        b_arg_os_mem=1
        ;;
    "-yuv0")
        b_arg_yuv_type0=1
        ;;
    "-total")
        b_arg_total_mem=1
        ;;
    "-restore")
        b_arg_restore=1
        ;;
    esac
done
#######################parse arg end########################
if [ $os_mem_size -ge $mem_total ]; then
    echo "[err] os_mem[$os_mem_size], over total_mem[$mem_total]"
    exit
fi

calc_mmz_info

#######################Action###############################

if [ $# -lt 1 ]; then
    load_usage
    exit 0
fi

# Sensor config
# SENSOR=${SENSOR:=imx307}
#
if [ -n "$SENSOR" ]; then
    logger -s -p daemon.info -t hisilicon "Manualy set SENSOR as ${SENSOR}"
else
    if fw_printenv -n sensor >/dev/null; then
        SENSOR_ENV=$(fw_printenv -n sensor)
        export SENSOR=${SENSOR_ENV}
        logger -s -p daemon.info -t hisilicon "Get data from environment and set SENSOR as ${SENSOR}"
    else
        insert_detect
        SENSOR_DETECT=$(ipcinfo --short-sensor)
        export SENSOR=${SENSOR_DETECT:=unknown}
        remove_detect
        logger -s -p daemon.info -t hisilicon "Get data from ipcinfo and set SENSOR as ${SENSOR}"
        fw_setenv sensor $SENSOR && logger -s -p daemon.info -t hisilicon "Write detected ${SENSOR} to U-Boot ENV"
    fi
fi

if [ $b_arg_remove -eq 1 ]; then
    remove_ko
fi

if [ "$SENSOR" = "unknown" ]; then
    exit 1
else
    if [ $b_arg_insmod -eq 1 ]; then
        cd /lib/modules/4.9.37/hisilicon
        insert_ko
    fi
fi

if [ $b_arg_restore -eq 1 ]; then
    sys_restore
fi
